package com.itlong.cloud.commons.wechat.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.POJO.DTO.property.CarIssueDTO;
import com.itlong.cloud.POJO.DTO.property.PaymentParkingCostsDTO;
import com.itlong.cloud.POJO.PO.*;
import com.itlong.cloud.POJO.VO.app.AppPayParkFeeNoticeVO;
import com.itlong.cloud.POJO.VO.app.AppUserAndRoomInfoVO;
import com.itlong.cloud.POJO.VO.property.PropertyBalanceVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.commons.dao.IAccountBalanceDao;
import com.itlong.cloud.commons.dao.IBalanceChangeRecordDao;
import com.itlong.cloud.commons.dao.IPaymentTradeDao;
import com.itlong.cloud.commons.dao.IUpdateUserAndRoomForbiddenStatusDao;
import com.itlong.cloud.commons.wechat.service.IWeChatPayService;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.property.dao.IPropertyWithdrawDao;
import com.itlong.cloud.property.service.IPropertyWithdrawService;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.encrypt.Md5EncryptUtil;
import com.itlong.cloud.utils.network.http.HttpProtocolUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.node.XMLParser;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.random.RandomUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.zip.GZIPInputStream;

/**
 * <desc>
 * 微信支付业务逻辑处理层
 * </desc>
 *
 * @createDate 2018/4/23
 */
@Service
public class WeChatPayServiceImpl implements IWeChatPayService {
    private static Logger LOG = LoggerFactory.getLogger(WeChatPayServiceImpl.class);

    @Autowired
    private IPaymentTradeDao iWechatPayDao;

    @Autowired
    private IBalanceChangeRecordDao iBalanceChangeRecordDao;

    @Autowired
    IAccountBalanceDao iAccountBalanceDao;

    @Autowired
    IPropertyWithdrawDao iPropertyWithdrawDao;

    @Autowired
    IUpdateUserAndRoomForbiddenStatusDao iUpdateUserAndRoomForbiddenStatusDao;

    //预支付统一下单请求地址
    @Value("${" + PlatformConstants.PREPAYURL + "}")
    public String PREPAYURL;

    //查询订单请求地址
    @Value("${" + PlatformConstants.ORDERURL + "}")
    public String ORDERURL;

    //商户APPID
    @Value("${" + PlatformConstants.APPID + "}")
    public String APPID;

    //商户号
    @Value("${" + PlatformConstants.MCHID + "}")
    public String MCHID;

    //应用市场APP名称-实际商品名称
    @Value("${" + PlatformConstants.BODY + "}")
    public String BODY;

    //正式版异步通知回调地址
    @Value("${" + PlatformConstants.NOTIFY_URL + "}")
    public String NOTIFY_URL;

    //演示版支付异步通知回调地址
    @Value("${" + PlatformConstants.SHOW_NOTIFY_URL + "}")
    public String SHOW_NOTIFY_URL;

    //交易类型
    @Value("${" + PlatformConstants.TRADE_TYPE + "}")
    public String TRADE_TYPE;

    //扩展字段
    @Value("${" + PlatformConstants.PACKAGE + "}")
    public String PACKAGE;

    //密钥KEY
    @Value("${" + PlatformConstants.KEY_APPSECRET + "}")
    public String KEY_APPSECRET;

    @Value("${" + PlatformConstants.APP_USER_TOKEN_KEY + "}")
    public String APP_USER_TOKEN_KEY;

    //下载账单URL
    @Value("${" + PlatformConstants.DOWNLOADB_BILL_URL + "}")
    public String DOWNLOADB_BILL_URL;

    @Value("${" + PlatformConstants.FILE_FTP_HOST + "}")
    public String FILE_FTP_HOST;

    @Value("${" + PlatformConstants.FILE_FTP_PORT + "}")
    public String FILE_FTP_PORT;

    @Value("${" + PlatformConstants.FILE_FTP_USERNAME + "}")
    public String FILE_FTP_USERNAME;

    @Value("${" + PlatformConstants.FILE_FTP_PASSWORD + "}")
    public String FILE_FTP_PASSWORD;

    @Value("${" + PlatformConstants.WECHAT_OFFICIAL_APPID + "}")
    public String WECHAT_OFFICIAL_APPID;

    @Value("${" + PlatformConstants.WECHAT_OFFICIAL_SECRET + "}")
    public String WECHAT_OFFICIAL_SECRET;

    @Value("${" + PlatformConstants.MINI_PROGRAM_APPID + "}")
    public String MINI_PROGRAM_APPID;

    @Autowired
    private MessageSender messageSender;

    ExecutorService cachedThreadPool;

    @Autowired
    IPropertyWithdrawService iPropertyWithdrawService;

    @PostConstruct
    public void init() {
        cachedThreadPool = Executors.newFixedThreadPool(1);
    }

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * <desc>
     * 调微信后台统一下单接口/商户后台保存订单
     * <desc/>
     *
     * @param total   支付金额
     * @param billsId 账单编号
     * @param feeType 缴费类型 1物业费 2维修费 3临时车缴费 4月卡缴费 5共享电梯
     * @param openId  公众号支付需要用此参数，用户在公众号中的唯一标识
     * @param payType 支付类型 2app支付 3小程序支付 4公众号支付 5h5支付
     * @param deviceUnique 设备编号
     * @param times 次数
     * @param amount 金额
     * @return
     * @author Juguang.S
     * @createDate 2018/4/24
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Map<Object, Object> saveOrder(String total, String loginUserId, String billsId, String feeType, String openId, Integer payType,String deviceUnique,String roomId,String ip,String times,String amount) {

        try {
            Map<Object, Object> map = new HashMap<>();
            String keyAppSecret = KEY_APPSECRET;
            String mchId = MCHID;
            String appId = WECHAT_OFFICIAL_APPID;
            String outTradeNo = RandomUtil.getRandomStringByLength(32);
            //根据payType来进行传值区分
            if (payType == PaySourceEnum.WECHAT_OFFICIAL_SOURCE.getType()) {
                //公众号JSAPI支付
                String projectId = iWechatPayDao.getBillForProject(billsId.split(",")[0]);
                // 判断是否开启物业增值，如果开启，则按原来的走，未开启，则走新的授权支付流程，0是未开启
                ProjectPO projectPO = iWechatPayDao.getProjectInfo(projectId);
                if (projectPO.getPropertyValueOpen() == 0) {
                    // 查询该项目绑定的商户号
                    WeChatOfficialAuthInfoPO weChatOfficialAuthInfoPO = iWechatPayDao.getWeChatAuthMchId(projectId);
                    if (weChatOfficialAuthInfoPO != null && StringUtils.isNotBlank(weChatOfficialAuthInfoPO.getAppId())
                            && StringUtils.isNotBlank(weChatOfficialAuthInfoPO.getMchId()) && StringUtils.isNotBlank(weChatOfficialAuthInfoPO.getApiKey())) {
                        keyAppSecret = weChatOfficialAuthInfoPO.getApiKey();
                        mchId = weChatOfficialAuthInfoPO.getMchId();
                        appId = weChatOfficialAuthInfoPO.getAppId();
                    } else {
                        Map<Object, Object> returnMsg = new HashMap<>();
                        returnMsg.put("return_msg", "微信支付未配置参数，请联系物业解决");
                        returnMsg.put("status", 2);
                        return returnMsg;
                    }
                }
                map.put("appid", appId);
                map.put("trade_type", "JSAPI");
                map.put("openid", openId);
            } else if (payType == PaySourceEnum.WECHAT_MINI_SOURCE.getType()) {
                //小程序支付
                map.put("appid", MINI_PROGRAM_APPID);
                map.put("trade_type", "JSAPI");
                map.put("openid", openId);
            } else if (payType == PaySourceEnum.H5_SOURCE.getType()) {
                String projectId = "";
                //H5支付
                if(StringUtils.isNotEmpty(roomId)){
                    //此时billsId为套餐id，则需要根据房间id查询项目编号
                    projectId = iWechatPayDao.getProjectByRoomId(roomId);
                }else{
                    projectId = iWechatPayDao.getBillForProject(billsId.split(",")[0]);
                }
                // 判断是否开启物业增值，如果开启，则按原来的走，未开启，则走新的授权支付流程，0是未开启
                ProjectPO projectPO = iWechatPayDao.getProjectInfo(projectId);
                if (projectPO.getPropertyValueOpen()!=null && projectPO.getPropertyValueOpen() == 0) {
                    // 查询该项目绑定的商户号
                    WeChatOfficialAuthInfoPO weChatOfficialAuthInfoPO = iWechatPayDao.getWeChatAuthMchId(projectId);
                    if (weChatOfficialAuthInfoPO != null && StringUtils.isNotBlank(weChatOfficialAuthInfoPO.getAppId())
                            && StringUtils.isNotBlank(weChatOfficialAuthInfoPO.getMchId()) && StringUtils.isNotBlank(weChatOfficialAuthInfoPO.getApiKey())) {
                        keyAppSecret = weChatOfficialAuthInfoPO.getApiKey();
                        mchId = weChatOfficialAuthInfoPO.getMchId();
                        appId = weChatOfficialAuthInfoPO.getAppId();
                    } else {
                        Map<Object, Object> returnMsg = new HashMap<>();
                        returnMsg.put("return_msg", "微信支付未配置参数，请联系物业解决");
                        returnMsg.put("status", 2);
                        return returnMsg;
                    }
                }
                map.put("appid", appId);
                map.put("trade_type", "MWEB");
            } else if (payType == PaySourceEnum.NATIVE_SOURCE.getType()) {
                //原生扫码支付
                map.put("appid", WECHAT_OFFICIAL_APPID);
                map.put("trade_type", "NATIVE");
                map.put("product_id",outTradeNo);
            } else {
                //APP支付
                map.put("appid", APPID);
                map.put("trade_type", TRADE_TYPE);
            }
            map.put("mch_id", mchId);
            map.put("nonce_str", RandomUtil.getRandomStringByLength(32));
            map.put("body", "云半径-微信支付");
            map.put("out_trade_no", outTradeNo);

            //处理金额去除小数点
            DecimalFormat decimalFormat = new DecimalFormat("0");
            decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
            BigDecimal big = new BigDecimal(total).multiply(new BigDecimal("100"));

            map.put("total_fee", Integer.parseInt(decimalFormat.format(big)));
            if(StringUtils.isNotEmpty(ip)){
                map.put("spbill_create_ip", ip);
            }else{
                map.put("spbill_create_ip", RandomUtil.getHostIp());
            }
            LOG.info("【统一下单】spbill_create_ip："+map.get("spbill_create_ip"));
            if (billsId == "") {
                map.put("notify_url", SHOW_NOTIFY_URL);
            } else {
                map.put("notify_url", NOTIFY_URL);
            }

            //根据算法生成签名
            String sign = Md5EncryptUtil.getWechatSign(map, keyAppSecret);
            map.put("sign", sign);

            //将参数转换成xml
            String paramXML = XMLParser.converterPayPalm(map);

            //通过HTTPS请求调用微信的统一下单请求
            String responseXML = HttpProtocolUtil.httpPost(PREPAYURL, paramXML);
            Map<Object, Object> returnData = new HashMap<>();
            if (StringUtils.isBlank(responseXML)) {
                returnData.put("return_msg", "服务器通讯暂时不可用，请稍后再试！");
                returnData.put("status", 1);
                return returnData;
            }

            //检验API返回的数据里面的签名是否合法，避免数据在传输的过程中被第三方篡改.
            Boolean bo = Md5EncryptUtil.checkWechatResponseSign(responseXML, keyAppSecret);
            if (!bo) {
                returnData.put("return_msg", "统一下单签名非法，商户号或者API密钥填写错误");
                returnData.put("status", 1);
                return returnData;
            }

            //将返回数据XML转为Map格式
            Map<Object, Object> responseMap = XMLParser.xmlString2Map(responseXML);

            PaymentTradePO paymentTradePO;
            if (responseMap.get("return_code").toString().contains("SUCCESS") && responseMap.get("result_code").toString().contains("SUCCESS")) {

                paymentTradePO = new PaymentTradePO();
                paymentTradePO.setTradeId(map.get("out_trade_no").toString());
                paymentTradePO.setPayType(PaymentTypeEnum.WECHAT_PAY.getType());
                paymentTradePO.setPrice(new BigDecimal(total));
                paymentTradePO.setUserId(loginUserId);
                paymentTradePO.setSuccessReturn(PaySuccessReturnEnum.IS_NOT_RETURN.getType());
                paymentTradePO.setTradeStatus(PayStatusEnum.WAIT_PAY.getType());
                paymentTradePO.setCreateTime(new Date());
                paymentTradePO.setStatus(DataStatusEnum.NORMAL.getType());
                paymentTradePO.setFeeType(feeType);
                paymentTradePO.setDeviceUnique(deviceUnique);
                paymentTradePO.setMchId(mchId);
                paymentTradePO.setAmount(amount);
                paymentTradePO.setTimes(times);
                if (StringUtils.isNotEmpty(billsId)) {
                    paymentTradePO.setFeeId(billsId);
                }
                if (StringUtils.isNotEmpty(roomId)) {
                    paymentTradePO.setRoomId(roomId);
                }

                //统一下单成功后保存商户后台系统的订单表
                iWechatPayDao.save(SqlUtil.durableData(paymentTradePO, PlatformConstants.TABLE_SAVE));
                //处理返回APP端的参数及生成sign
                Map<Object, Object> resultMap = new HashMap<>();
                if (payType != PaySourceEnum.APP_SOURCE.getType()) {
                    //处理公众号JSAPI 小程序支付 H5支付
                    if (payType == PaySourceEnum.WECHAT_OFFICIAL_SOURCE.getType()) {
                        resultMap.put("appId", appId);
                    } else if (payType == PaySourceEnum.H5_SOURCE.getType()) {
                        resultMap.put("appId", appId);
                        resultMap.put("mweb_url", responseMap.get("mweb_url").toString());
                    } else if (payType == PaySourceEnum.NATIVE_SOURCE.getType()) {
                        resultMap.put("appId", WECHAT_OFFICIAL_APPID);
                        resultMap.put("codeUrl", responseMap.get("code_url").toString());
                    }else {
                        resultMap.put("appId", MINI_PROGRAM_APPID);
                    }
                    resultMap.put("signType", "MD5");
                    resultMap.put("package", String.format("%s%s", "prepay_id=", responseMap.get("prepay_id").toString()));
                    resultMap.put("timeStamp", DateUtil.getSecondTimestamp(new Date()));
                    resultMap.put("nonceStr", RandomUtil.getRandomStringByLength(32));
                } else {
                    //处理APP支付
                    resultMap.put("appid", APPID);
                    resultMap.put("partnerid", mchId);
                    resultMap.put("prepayid", responseMap.get("prepay_id").toString());
                    resultMap.put("package", PACKAGE);
                    resultMap.put("timestamp", DateUtil.getSecondTimestamp(new Date()));
                    resultMap.put("noncestr", RandomUtil.getRandomStringByLength(32));
                }

                //根据算法生成签名
                String returnSign = Md5EncryptUtil.getWechatSign(resultMap, keyAppSecret);
                if (payType != PaySourceEnum.APP_SOURCE.getType()) {
                    resultMap.put("paySign", returnSign);
                } else {
                    resultMap.put("sign", returnSign);
                }

                //status 0代表统一下单成功  1代表微信系统后台返回sign不合法 2代表与微信后台交互其它原因
                resultMap.put("status", 0);
                resultMap.put("tradeId", map.get("out_trade_no").toString());
                return resultMap;
            } else {
                Map<Object, Object> returnMsg = new HashMap<>();
                returnMsg.put("return_msg", responseMap.get("err_code_des"));
                returnMsg.put("status", 2);
                return returnMsg;
            }

        } catch (Exception e) {
            throw new DataAccessException("【App_微信支付】统一下单失败", e);
        }
    }


    /**
     * <desc>
     * 微信支付结果回调通知
     * <desc/>
     *
     * @param
     * @return
     * @author Juguang.S
     * @createDate 2018/4/25
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public AppPayParkFeeNoticeVO payResultNotice(String rturnInfo) {
        LOG.info("【微信回调返回】" + rturnInfo);
        AppPayParkFeeNoticeVO payParkFeeNoticeVO = new AppPayParkFeeNoticeVO();
        PaymentParkingCostsDTO costsDTO = null;
        CarIssueDTO carIssueDTO = new CarIssueDTO();
        String wechatReturnNotice = "<xml>\n" + "  <return_code><![CDATA[SUCCESS]]></return_code>\n" + "  <return_msg><![CDATA[OK]]></return_msg>\n" + "</xml>";
        try {
            String keyAppSecret = KEY_APPSECRET;
            //对微信后台请求传参进行转换格式及校验sign是否合法
            Map<Object, Object> paramMap = XMLParser.xmlString2Map(rturnInfo);
            if (StringUtils.isNotEmpty(paramMap.get("return_code").toString()) && paramMap.get("return_code").toString().equals("SUCCESS")) {
                PaymentTradePO orderPO = iWechatPayDao.getOrderByTradeId(paramMap.get("out_trade_no").toString());
                if (paramMap.get("mch_id") != null && StringUtils.isNotBlank(paramMap.get("mch_id").toString()) && !paramMap.get("mch_id").toString().equals(MCHID)) {
                    String projectId = iWechatPayDao.getBillForProject(orderPO.getFeeId());
                    WeChatOfficialAuthInfoPO weChatAuthMchId = iWechatPayDao.getWeChatAuthMchId(projectId);
                    if (weChatAuthMchId != null) {
                        keyAppSecret = weChatAuthMchId.getApiKey();
                    }
                }
                Boolean bo = Md5EncryptUtil.checkWechatResponseSign(rturnInfo, keyAppSecret);

                //校验支付通知返回的金额和下订单时数据库保存的金额的一致性及sign的合法性
                if (!bo) {
                    return null;
                }
                payParkFeeNoticeVO.setDeviceUnique(orderPO.getDeviceUnique());
                payParkFeeNoticeVO.setUserId(orderPO.getUserId());

                //商户系统对处理重复的通知的校验  根据商户订单号从数据库中查出该订单的是否收到支付后的回调
                if (orderPO.getSuccessReturn() == PaySuccessReturnEnum.IS_RETURN.getType()) {
                    payParkFeeNoticeVO.setWechatReturnNotice(wechatReturnNotice);
                    payParkFeeNoticeVO.setMark(1);
                    return payParkFeeNoticeVO;
                }

                if (!orderPO.getFeeType().equals("3") && !orderPO.getFeeType().equals("7")) {
                    String reg = "(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})";
                    String date = paramMap.get("time_end").toString().replaceAll(reg, "$1/$2/$3 $4:$5:$6");
                    orderPO.setSuccessTime(new Date(date));
                    orderPO.setUpdateTime(new Date());
                    orderPO.setTradeStatus(PayStatusEnum.SUCCESS_PAY.getType());
                    orderPO.setTransactionId(paramMap.get("transaction_id").toString());
                    orderPO.setSuccessReturn(PaySuccessReturnEnum.IS_RETURN.getType());
                    iWechatPayDao.update(SqlUtil.durableData(orderPO, PlatformConstants.TABLE_UPDATE));
                    if(orderPO.getFeeType().equals("6")){
                        //如果微信支付为云服务费，则在此对云服务费订单和该订单对应的批次号下的云对讲设备推送指令
                        List<DeviceBusinessChangeLogPO> changeLogPOS = new ArrayList<>();
                        JSONArray jsonArray = new JSONArray();
                        iWechatPayDao.updateCloudServiceCostOrder(orderPO.getFeeId());
                        List<Map<String,String>> deviceList = iWechatPayDao.getDeviceInfoByBatchNumber(orderPO.getFeeId());
                        if(deviceList!=null && !deviceList.isEmpty()){
                            List<Map<String, String>> allDeviceList = iWechatPayDao.getCloudTalkInfoByProjectId(deviceList.get(0).get("projectId"));
                            if(allDeviceList != null && !allDeviceList.isEmpty()) {
                                for (Map<String, String> map : allDeviceList) {
                                    if(StringUtils.isEmpty(map.get("deviceUnique"))){
                                        continue;
                                    }
                                    JSONObject jsonObject = new JSONObject();
                                    jsonObject.put("deviceUnique", map.get("deviceUnique"));
                                    jsonArray.add(jsonObject);
                                }
                            }
                            //处理多个批次号复用时合为一个新的批次号的设备批次号信息
                            if(StringUtils.isNotEmpty(deviceList.get(0).get("oldBatchNumber"))){
                                iWechatPayDao.updateElevatorBatchNumber(deviceList.get(0).get("oldBatchNumber").split(","), deviceList.get(0).get("batchNumber"));
                                iWechatPayDao.updateEntranceBatchNumber(deviceList.get(0).get("oldBatchNumber").split(","), deviceList.get(0).get("batchNumber"));
                                iWechatPayDao.updateCloudIntercomBatchNumber(deviceList.get(0).get("oldBatchNumber").split(","), deviceList.get(0).get("batchNumber"));
                                iWechatPayDao.updatePadBatchNumber(deviceList.get(0).get("oldBatchNumber").split(","), deviceList.get(0).get("batchNumber"));
                            }
                        }
                        payParkFeeNoticeVO.setWechatReturnNotice(wechatReturnNotice);

                        //项目云服务费变更后需通知云对讲
                        if (!jsonArray.isEmpty()) {
                            DeviceBusinessChangeLogPO changeLogPO = new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_DEVICE, jsonArray, deviceList.get(0).get("projectId"));
                            changeLogPOS.add(changeLogPO);
                        }
                        //向设备推送设备云对讲指令
                        if (!changeLogPOS.isEmpty()) {
                            JSONObject dataJs = new JSONObject();
                            dataJs.put("data", changeLogPOS);
                            //云对讲
                            messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                                    JsonUtil.toJSON(dataJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                                    RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
                        }

                        return payParkFeeNoticeVO;
                    }
                } else if (("7").equals(orderPO.getFeeType()))
                {//共享电梯支付
                    //查询套餐相关信息
                    Map<String,Object> map = iWechatPayDao.getMealInfoByTradeId(orderPO.getTradeId());
                    //更新property_room_qrcode_batch_record中的次数
                    Date nowTime = new Date();
                    PropertyRoomQrcodeBatchRecordPO propertyRoomQrcodeBatchRecordPO = new PropertyRoomQrcodeBatchRecordPO();
                    propertyRoomQrcodeBatchRecordPO.setQrcodeBatchRecordId(LogicIdUtil.bussinessId());
                    propertyRoomQrcodeBatchRecordPO.setRoomId(map.get("roomId").toString());
                    PropertyRoomQrcodeBatchRecordPO roomQrCodeBatch = iWechatPayDao.getRoomQrCodeBatch(map.get("roomId").toString());
                    if (roomQrCodeBatch != null && roomQrCodeBatch.getId() != null) {
                        propertyRoomQrcodeBatchRecordPO.setBatch(roomQrCodeBatch.getBatch() + 1);
                    } else {
                        propertyRoomQrcodeBatchRecordPO.setBatch(1);
                        roomQrCodeBatch = new PropertyRoomQrcodeBatchRecordPO();
                        roomQrCodeBatch.setUsableCount(0);
                    }
                    //修改了金额、次数的取值来源，由原来的map变为 PaymentTradePO 实体中取值
                    propertyRoomQrcodeBatchRecordPO.setPayCount(Integer.parseInt(orderPO.getTimes()));
                    propertyRoomQrcodeBatchRecordPO.setCount(Integer.parseInt(orderPO.getTimes())+roomQrCodeBatch.getUsableCount());
                    propertyRoomQrcodeBatchRecordPO.setUsableCount(Integer.parseInt(orderPO.getTimes())+roomQrCodeBatch.getUsableCount());
                    propertyRoomQrcodeBatchRecordPO.setStatus(DataStatusEnum.NORMAL.getType());
                    propertyRoomQrcodeBatchRecordPO.setCreateTime(nowTime);
                    iWechatPayDao.save(SqlUtil.durableData(propertyRoomQrcodeBatchRecordPO, PlatformConstants.TABLE_SAVE));
                    //更新payment_trade表
                    String reg = "(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})";
                    String date = paramMap.get("time_end").toString().replaceAll(reg, "$1/$2/$3 $4:$5:$6");
                    orderPO.setSuccessTime(new Date(date));
                    orderPO.setUpdateTime(new Date());
                    orderPO.setTradeStatus(PayStatusEnum.SUCCESS_PAY.getType());
                    orderPO.setTransactionId(paramMap.get("transaction_id").toString());
                    orderPO.setSuccessReturn(PaySuccessReturnEnum.IS_RETURN.getType());
                    iWechatPayDao.update(SqlUtil.durableData(orderPO, PlatformConstants.TABLE_UPDATE));
                    //新增payment_record表
                    PaymentRecordPO paymentRecordPO = new PaymentRecordPO();
                    paymentRecordPO.setPaymentId(LogicIdUtil.bussinessId());
                    paymentRecordPO.setMealId(map.get("mealId").toString());
                    paymentRecordPO.setRoomId(map.get("roomId").toString());
                    paymentRecordPO.setProjectId(map.get("projectId").toString());
                    paymentRecordPO.setRecordType(1);
                    paymentRecordPO.setPaymentType(1);
                    paymentRecordPO.setPaymentAmount(orderPO.getAmount());
                    paymentRecordPO.setPaymentCount(Integer.parseInt(orderPO.getTimes()));
                    paymentRecordPO.setStatus(DataStatusEnum.NORMAL.getType());
                    paymentRecordPO.setCreateTime(nowTime);
                    paymentRecordPO.setCreateUserId(orderPO.getUserId());
                    paymentRecordPO.setOperateUserId(orderPO.getUserId());
                    iWechatPayDao.save(SqlUtil.durableData(paymentRecordPO, PlatformConstants.TABLE_SAVE));
                    Map<String,Object> blackList = new HashMap<>();
                    blackList.put("projectId", map.get("projectId"));
                    blackList.put("roomId", map.get("roomId"));
                    List<DeviceBusinessElevatorChangeLogPO> elevatorChanges = new ArrayList<>();
                    DeviceBusinessElevatorChangeLogPO elevatorPo = new DeviceBusinessElevatorChangeLogPO(map.get("projectId").toString(), CloudElevatorChangeBusinessEnum.PUSH_BLACK_LIST, JsonUtil.toJSON(blackList));
                    elevatorChanges.add(elevatorPo);
                    JSONObject pushJs = new JSONObject();
                    pushJs.put("data", elevatorChanges);
                    //推送云电梯业务指令
                    messageSender.send(
                            RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                            JsonUtil.toJSON(pushJs),
                            RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                            RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
                    return payParkFeeNoticeVO;
                }

                if (orderPO.getFeeType().equals("3")) {
                    orderPO.setTransactionId(paramMap.get("transaction_id").toString());
                    iWechatPayDao.update(SqlUtil.durableData(orderPO, PlatformConstants.TABLE_UPDATE));
                }
                String[] feeIds = orderPO.getFeeId().split(",");
                String projectId = iWechatPayDao.getBillForProject(feeIds[0]);

                //获取手续费利率
                PropertyBalanceVO result = iPropertyWithdrawService.getThirdPartyPaymentInfo();

                // 多账单缴费，限欠费名单，则轮流判断账单是否需要收取增值费
                BigDecimal profitMoney = new BigDecimal("0");
                String profitAddress = "";
                if ("1".equals(orderPO.getFeeType()) && feeIds.length > 1) {
                    for (String feeId : feeIds) {
                        if (StringUtils.isNotBlank(iWechatPayDao.getRoomManage(feeId))) {
                            String paidAmount = iWechatPayDao.getPaidAmountByFeeId(feeId);
                            String billAddress = iWechatPayDao.getBillAddress(feeId);
                            if ("".equals(profitAddress)) {
                                profitAddress = billAddress;
                            } else if (!profitAddress.contains(billAddress)){
                                profitAddress = profitAddress + "、" + billAddress;
                            }
                            profitMoney = profitMoney.add(new BigDecimal(paidAmount));
                        }
                    }
                    LOG.info("计算多账单收取物业增值前费用：" + profitMoney.toString());
                }

                //由于总账单中的所需支付的金额是由抄表费和物业费两类型数据的总和，此处逻辑是为了处理先支付了一种类型后又生成了另一种类型的费用的情况
                //判断是否是某一账单的二次支付
                for (String feeId : feeIds) {
                    Integer meterPayStatus = iWechatPayDao.getBillStatusByType(MeterInfoTypeEnum.WATERRATE.getType().toString(), feeId);
                    Integer propertyPayStatus = iWechatPayDao.getBillStatusByType("4", feeId);
                    DecimalFormat df = new DecimalFormat("#.00");
                    String wechatPayTotal = df.format(Double.valueOf(paramMap.get("total_fee").toString()) / 100).toString();
                    //抄表费 应缴 实缴 滞纳金
                    Map<String, Object> meterPayTotal = iWechatPayDao.getMeterPayTotal(feeId);
                    if (meterPayTotal == null || meterPayTotal.size() == 0) {
                        meterPayTotal = new HashMap<>();
                        meterPayTotal.put("dueAmount", "");
                        meterPayTotal.put("paidAmount", "");
                        meterPayTotal.put("penalty", "");
                    }
                    //物业费 应缴 实缴 滞纳金
                    Map<String, Object> propertyPayTotal = iWechatPayDao.getPropertyPayTotal(feeId);
                    if (propertyPayTotal == null || propertyPayTotal.size() == 0) {
                        propertyPayTotal = new HashMap<>();
                        propertyPayTotal.put("dueAmount", "");
                        propertyPayTotal.put("paidAmount", "");
                        propertyPayTotal.put("penalty", "");
                    }
                    //物业费+抄表费 应缴 实缴 滞纳金
                    Map<String, Object> billPayTotal = iWechatPayDao.getBillPayTotal(feeId);

                    PropertyPaymentBillPO billPO = new PropertyPaymentBillPO();
                    billPO.setFeeId(feeId);
                    billPO.setFeeStatus(2);
                    billPO.setPaymentType(PaymentTypeEnum.WECHAT_PAY.getType());
                    billPO.setOriginPay(PaySourceEnum.APP_SOURCE.getType());
                    billPO.setPayTime(new Date());
                    billPO.setUpdateTime(new Date());
                    billPO.setUserId(orderPO.getUserId());

                    if ((meterPayStatus > 0 && propertyPayStatus == 0) || (meterPayStatus == 0 && propertyPayStatus > 0)) {
                        //为同一账单进行第二次支付
                        if (propertyPayStatus == 0) {
                            iWechatPayDao.updatePayStatus(new String[]{"4"}, feeId);
                        }
                        if (meterPayStatus == 0) {
                            iWechatPayDao.updatePayStatus(new String[]{"1", "2", "3"}, feeId);
                        }
                        //更新总账单中的应缴 实缴 滞纳金 支付状态
                        billPO.setDueAmount(new BigDecimal(billPayTotal.get("dueAmount").toString()));
                        billPO.setPaidAmount(new BigDecimal(billPayTotal.get("paidAmount").toString()));
                        if (billPayTotal.get("penalty") == null) {
                            billPO.setPenalty(new BigDecimal("0.00"));
                        } else {
                            billPO.setPenalty(new BigDecimal(billPayTotal.get("penalty").toString()));
                        }
                        iWechatPayDao.update(SqlUtil.durableData(billPO, PlatformConstants.TABLE_UPDATE));

                    } else {
                        //根据账单号查询并修改支付成功后的账单信息
                        //如果支付类型为维修则直接更新账单orderPO
                        if (("2").equals(orderPO.getFeeType()) || ("5").equals(orderPO.getFeeType())) {
                            billPO.setPaidAmount(BigDecimal.valueOf(Double.valueOf(paramMap.get("total_fee").toString()) / 100));
                            billPO.setDueAmount(BigDecimal.valueOf(Double.valueOf(paramMap.get("total_fee").toString()) / 100));
                            iWechatPayDao.update(SqlUtil.durableData(billPO, PlatformConstants.TABLE_UPDATE));
                            if (("5").equals(orderPO.getFeeType())) {//临时通行权限下发
                                String roomIds = iWechatPayDao.getRoomIdsByUser(orderPO.getUserId(),projectId);
                                // 获取房间id添加返回
                                payParkFeeNoticeVO.setRoomId(roomIds);
                                String[] roomIdAll = roomIds.split(",");
                                //临时通行暂时将所有当前项目下此用户房间改为未欠费
                                iWechatPayDao.updateRoomArrearageStatusByFeeId(orderPO.getUserId(),projectId, 0);
                                iWechatPayDao.updateUserProject(orderPO.getUserId(), projectId, 0);
                                List<DeviceBusinessChangeLogPO> changes = new ArrayList<>();
                                List<DeviceBusinessElevatorChangeLogPO> elevatorChanges = new ArrayList<>();
                                List<DeviceBusinessEntranceChangeLogPO> entranceChanges = new ArrayList<>();
                                List<Map<String, Object>> roomList = new ArrayList<>();
                                for (String roomId : roomIdAll) {
                                    Map<String, Object> roomMap = new HashMap<>();
                                    roomMap.put("roomId", roomId);
                                    roomList.add(roomMap);
                                }
                                //推送房间更新消息
                                DeviceBusinessChangeLogPO po = new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_ROOM, JsonUtil.toJSON(roomList), projectId);
                                changes.add(po);
                                DeviceBusinessElevatorChangeLogPO elevatorPo = new DeviceBusinessElevatorChangeLogPO(projectId, CloudElevatorChangeBusinessEnum.PUSH_ROOM_PWD, JsonUtil.toJSON(roomList));
                                elevatorChanges.add(elevatorPo);
                                DeviceBusinessEntranceChangeLogPO entrancePO = new DeviceBusinessEntranceChangeLogPO(projectId, CloudEntranceChangeBusinessEnum.PUSH_ROOM_PWD, JsonUtil.toJSON(roomList));
                                entranceChanges.add(entrancePO);
                                JSONObject dataJs = new JSONObject();
                                dataJs.put("data", changes);
                                //发送云对讲业务指令
                                messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE, JsonUtil.toJSON(dataJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE, RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
                                dataJs.put("data", elevatorChanges);
                                //推送云电梯房间信息
                                messageSender.send(
                                        RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                                        JsonUtil.toJSON(dataJs),
                                        RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                                        RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
                                //发送云门禁指令
                                dataJs.put("data", entranceChanges);
                                messageSender.send(
                                        RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                                        JSON.toJSONString(dataJs),
                                        RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                                        RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
                                );
                            }
                        } else if (("3").equals(orderPO.getFeeType())) {
                            BigDecimal totalBigDecimal = new BigDecimal(paramMap.get("total_fee").toString());
                            BigDecimal handFee = totalBigDecimal.divide(new BigDecimal("100")).multiply(new BigDecimal(result.getWechatHandlingFee())).multiply(new BigDecimal("0.01"));
                            DecimalFormat dformat = new DecimalFormat("0.00");
                            dformat.setRoundingMode(RoundingMode.HALF_UP);
                            handFee = new BigDecimal(dformat.format(handFee));
                            String realTotal = totalBigDecimal.divide(new BigDecimal("100")).subtract(handFee).toString();
                            //所缴费类型为临时车时将账单ID和金额传入消息队列
                            Map<String, Object> params = new HashMap<>();
                            params.put("feeId", orderPO.getFeeId());
                            params.put("realTotal", realTotal);
                            params.put("projectId", projectId);
                            params.put("transactionId", orderPO.getTransactionId());
                            params.put("tradeId", orderPO.getTradeId());
                            params.put("account", totalBigDecimal.divide(new BigDecimal("100")).toString());

                            messageSender.send(RabbitMQConstant.RABBITMQ_PARKING_BILL_PEY_MANAGER_QUEUE, JSON.toJSONString(params),
                                    RabbitMQConstant.RABBITMQ_PROJECT_EXCHANGE,
                                    RabbitMQConstant.RABBITMQ_PARKING_BILL_PEY_ROUTING_KEY);
                            // 此处需要将临时车缴费后的信息告知富士
                            costsDTO = iWechatPayDao.getTemCarInfoByBillId(orderPO.getFeeId());
                            costsDTO.setProjectId(projectId);
                            costsDTO.setCarType("2C");
                            costsDTO.setFreeMoney(new BigDecimal("0"));
                            costsDTO.setPayType("2");
                            costsDTO.setReDate(sdf2.format(new Date()));
                        } else if (("4").equals(orderPO.getFeeType())) {
                            Map<String, Object> carMap = iWechatPayDao.getPropertyPaymentBillInfo(orderPO.getFeeId());
                            iWechatPayDao.update(SqlUtil.durableData(billPO, PlatformConstants.TABLE_UPDATE));
                            //根据账单ID查询车牌号
                            Map<String, String> map = iWechatPayDao.getCarNumByBillId(orderPO.getFeeId());
                            carIssueDTO.setPlate(map.get("plateNumber"));
                            carIssueDTO.setMoney(new BigDecimal(Double.valueOf(paramMap.get("total_fee").toString()) / 100));
                            //根据carId判断此次是否是首次交月卡费
                            String carid = map.get("carId");
                            Integer count = iWechatPayDao.getFirstPayMonthCardFee(map.get("carId"), projectId);
                            if (iWechatPayDao.getFirstPayMonthCardFee(map.get("carId"), projectId) > 0) {
                                carIssueDTO.setType(2);
                            } else {
                                carIssueDTO.setType(1);
                            }
                            carIssueDTO.setProjectId(projectId);
                            carIssueDTO.setPayType(2);
                            //保存月卡车缴费记录
                            PropertyCardPaymentRecordPO recordPO = new PropertyCardPaymentRecordPO();
                            recordPO.setCarId(carMap.get("carId").toString());
                            recordPO.setMonthCardId(carMap.get("monthCardId").toString());
                            recordPO.setFeeId(orderPO.getFeeId());
                            recordPO.setProjectId(carMap.get("projectId").toString());
                            recordPO.setMonth(Integer.valueOf(carMap.get("month").toString()));
                            PropertyCardPaymentRecordPO paymentRecordPO = this.saveMonthCardFeeRecord(recordPO);

                            // 此处需要将月卡缴费后的截止时间告知富士
                            carIssueDTO.setBeginDate(sdf2.format(paymentRecordPO.getStartTime()));
                            carIssueDTO.setEndDate(sdf2.format(paymentRecordPO.getEndTime()));

                        } else if (wechatPayTotal.equals(meterPayTotal.get("paidAmount").toString()) && StringUtils.isNotEmpty(propertyPayTotal.get("paidAmount").toString())
                                && new BigDecimal(billPayTotal.get("paidAmount").toString()).compareTo(orderPO.getPrice()) == 1) {
                            //此种考虑：当只有一种类型的费用在调起微信支付时，又生成了另一种类型的子账单的情况 如果支付金额等于子账单抄表费的情况 修改子账单抄表费的支付状态，将子账单物业物业费的应缴 实缴 滞纳金更新至总账单中
                            PropertyPaymentBillPO PO = new PropertyPaymentBillPO();
                            PO.setDueAmount(new BigDecimal(propertyPayTotal.get("dueAmount").toString()));
                            PO.setPaidAmount(new BigDecimal(propertyPayTotal.get("paidAmount").toString()));
                            if (meterPayTotal.get("penalty") == null) {
                                PO.setPenalty(new BigDecimal("0.00"));
                            } else {
                                PO.setPenalty(new BigDecimal(propertyPayTotal.get("penalty").toString()));
                            }
                            PO.setFeeId(orderPO.getFeeId());
                            PO.setFeeStatus(1);
                            PO.setUpdateTime(new Date());
                            iWechatPayDao.update(SqlUtil.durableData(PO, PlatformConstants.TABLE_UPDATE));
                            iWechatPayDao.updatePayStatus(new String[]{"1", "2", "3"}, orderPO.getFeeId());
                        } else if (wechatPayTotal.equals(propertyPayTotal.get("paidAmount").toString()) && StringUtils.isNotEmpty(meterPayTotal.get("paidAmount").toString())
                                && new BigDecimal(billPayTotal.get("paidAmount").toString()).compareTo(orderPO.getPrice()) == 1) {
                            //此种考虑：当只有一种类型的费用在调起微信支付时，又生成了另一种类型的子账单的情况 如果支付金额等于子账单物业费的情况 修改子账单物业费的支付状态，将子账单物业抄表费的应缴 实缴 滞纳金更新至总账单中
                            PropertyPaymentBillPO PO = new PropertyPaymentBillPO();
                            PO.setDueAmount(new BigDecimal(meterPayTotal.get("dueAmount").toString()));
                            PO.setPaidAmount(new BigDecimal(meterPayTotal.get("paidAmount").toString()));
                            if (meterPayTotal.get("penalty") == null) {
                                PO.setPenalty(new BigDecimal("0.00"));
                            } else {
                                PO.setPenalty(new BigDecimal(meterPayTotal.get("penalty").toString()));
                            }
                            PO.setFeeId(orderPO.getFeeId());
                            PO.setFeeStatus(1);
                            PO.setUpdateTime(new Date());
                            iWechatPayDao.update(SqlUtil.durableData(PO, PlatformConstants.TABLE_UPDATE));
                            iWechatPayDao.updatePayStatus(new String[]{"4"}, orderPO.getFeeId());
                        } else {
                            //如果支付金额等于子账单抄表费和物业费的情况 修改总账单和子账单的支付状态(全等)
                            // 获取房间id添加返回
                            String roomIds = iWechatPayDao.getRoomIdsByUser(orderPO.getUserId(),projectId);
                            payParkFeeNoticeVO.setRoomId(roomIds);
                            iWechatPayDao.update(SqlUtil.durableData(billPO, PlatformConstants.TABLE_UPDATE));
                            iWechatPayDao.updatePayStatus(new String[]{"1", "2", "3", "4"}, feeId);
                        }
                    }
                }

                //计算出扣出微信手续费的金额
                BigDecimal totalBigDecimal = new BigDecimal(paramMap.get("total_fee").toString());
                BigDecimal handFee = totalBigDecimal.divide(new BigDecimal("100")).multiply(new BigDecimal(result.getWechatHandlingFee())).multiply(new BigDecimal("0.01"));
                DecimalFormat dformat = new DecimalFormat("0.00");
                dformat.setRoundingMode(RoundingMode.HALF_UP);
                handFee = new BigDecimal(dformat.format(handFee));
                String realTotal = totalBigDecimal.divide(new BigDecimal("100")).subtract(handFee).toString();

                //处理除了缴费类型为临时车缴费外的逻辑
                if (!"3".equals(orderPO.getFeeType())) {
                    //保存微信支付成功后的项目中物业可提现余额和实时余额需更新 发送消息队列
//                    ProjectPO projectInfo = iWechatPayDao.getProjectInfo(projectId);
                    // 判断是否开启物业增值，如果开启，则按原来的走，未开启，则走新的授权支付流程，0是未开启，原来的支付流程钱直接流向物业，不做实时余额的变动和资金变动明细的保存
                    // 因为要兼容旧版app的支付，所以用物业增值字段判断无法兼容，这里使用订单表中缴费去向的商户号来判断
                    if (MCHID.equals(orderPO.getMchId())/* || projectInfo.getPropertyValueOpen() == 1*/) {
                        Map<String, Object> params = new HashMap<>();
                        params.put("arithmeticFlag", "0");//运算: 0加,1减
                        params.put("amount", realTotal);//金额
                        params.put("projectId", projectId);//项目编号
                        params.put("updateNameFlag", 1);//0可提现余额,1实时余额   为空都更新

                        messageSender.send(RabbitMQConstant.RABBITMQ_PROJECT_AMOUNT_MANAGER_QUEUE, JSON.toJSONString(params),
                                RabbitMQConstant.RABBITMQ_PAY_EXCHANGE,
                                RabbitMQConstant.RABBITMQ_PROJECT_AMOUNT_ROUTING_KEY);

                        //保存微信支付成功后资金变动明细 发送消息队列
                        AmountChangeInfoPO changeInfoPO = new AmountChangeInfoPO(LogicIdUtil.bussinessId(),
                                BigDecimal.valueOf(Double.valueOf(paramMap.get("total_fee").toString()) / 100),
                                paramMap.get("transaction_id").toString(),
                                "", "");
                        changeInfoPO.setStatus(DataStatusEnum.NORMAL.getType());
                        changeInfoPO.setProjectId(projectId);
                        changeInfoPO.setCreateTime(new Date());
                        changeInfoPO.setThirdPartyPayment(1);
                        changeInfoPO.setHandlingFee(new BigDecimal("0"));
                        if (String.valueOf(TradeTypeEnum.REPAIR_FEE.getType()).equals(orderPO.getFeeType())) {
                            changeInfoPO.setTradeType(TradeTypeEnum.REPAIR_FEE.getType());
                        }
                        if (String.valueOf(TradeTypeEnum.PROPERTY_FEE.getType()).equals(orderPO.getFeeType())) {
                            changeInfoPO.setTradeType(TradeTypeEnum.PROPERTY_FEE.getType());
                        }
                        if ("4".equals(orderPO.getFeeType())) {
                            changeInfoPO.setTradeType(TradeTypeEnum.PARKING_FEE.getType());
                        }
                        if ("5".equals(orderPO.getFeeType())) {
                            changeInfoPO.setTradeType(TradeTypeEnum.TEMPORARY_PASSAGE_VALUE.getType());
                        }
                        JSONObject js = new JSONObject();
                        js.put("data", changeInfoPO);
                        messageSender.send(RabbitMQConstant.RABBITMQ_AMOUNT_CHANGE_INFO_MANAGER_QUEUE, JSON.toJSONString(js),
                                RabbitMQConstant.RABBITMQ_PAY_EXCHANGE,
                                RabbitMQConstant.RABBITMQ_AMOUNT_CHANGE_INFO_ROUTING_KEY);
                    }
                    BigDecimal shareProfitBalance = null;
                    if ("1".equals(orderPO.getFeeType()) || "5".equals(orderPO.getFeeType())) {
                        DecimalFormat decimalFormat = new DecimalFormat("0.00");
                        decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
                        // 物业增值费用扣除实时余额
                        ShareProfitRuleInfoPO shareProfitRuleInfoPO = iWechatPayDao.getShareProfitByProjectId(projectId);
                        if ("1".equals(orderPO.getFeeType()) && shareProfitRuleInfoPO != null) {
                            if ((shareProfitRuleInfoPO.getType() == 1 || (!orderPO.getFeeId().contains(",") && StringUtils.isNotBlank(iWechatPayDao.getRoomManage(orderPO.getFeeId()))))) {
                                BigDecimal realTotalValue = new BigDecimal(realTotal);
                                // 计算物业增值所收金额
                                shareProfitBalance = realTotalValue./*multiply(new BigDecimal(shareProfitRuleInfoPO.getProfitPercent())).divide(new BigDecimal("100")).*/
                                        multiply(new BigDecimal(shareProfitRuleInfoPO.getPlatformPercent())).divide(new BigDecimal("100")).
                                        setScale(2, BigDecimal.ROUND_HALF_UP);
                            } else {
                                if (!"0".equals(profitMoney.toString())) {
                                    LOG.info("使用多账单收取物业增值前费用：" + profitMoney.toString());
                                    // 计算模拟手续费，减去该收的手续费再收取增值费
                                    BigDecimal simulateHandFee = profitMoney.multiply(new BigDecimal(result.getWechatHandlingFee())).multiply(new BigDecimal("0.01"));
                                    simulateHandFee = new BigDecimal(dformat.format(simulateHandFee));
                                    shareProfitBalance = profitMoney.subtract(simulateHandFee).multiply(new BigDecimal(shareProfitRuleInfoPO.getPlatformPercent())).
                                            divide(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);

                                    Map<String, Object> balanceMap = new HashMap<>();
                                    balanceMap.put("arithmeticFlag", "1");//运算: 0加,1减
                                    balanceMap.put("amount", shareProfitBalance.toString());//金额
                                    balanceMap.put("projectId", projectId);//项目编号
                                    balanceMap.put("updateNameFlag", 1);//0可提现余额,1实时余额   为空都更新
                                    messageSender.send(RabbitMQConstant.RABBITMQ_PROJECT_AMOUNT_MANAGER_QUEUE, JSON.toJSONString(balanceMap),
                                            RabbitMQConstant.RABBITMQ_PAY_EXCHANGE,
                                            RabbitMQConstant.RABBITMQ_PROJECT_AMOUNT_ROUTING_KEY);

                                    //保存收取物业增值费用后资金变动明细 发送消息队列
                                    AmountChangeInfoPO profitAmountChangePO = new AmountChangeInfoPO(LogicIdUtil.bussinessId(),
                                            shareProfitBalance, paramMap.get("transaction_id").toString(), "", "");
                                    profitAmountChangePO.setStatus(DataStatusEnum.NORMAL.getType());
                                    profitAmountChangePO.setProjectId(projectId);
                                    profitAmountChangePO.setCreateTime(new Date());
                                    profitAmountChangePO.setThirdPartyPayment(1);
                                    profitAmountChangePO.setHandlingFee(new BigDecimal("0"));
                                    profitAmountChangePO.setRemark(profitAddress + "物业增值分润扣除");
                                    profitAmountChangePO.setTradeType(TradeTypeEnum.PROPERTY_ADD_VALUE.getType());
                                    JSONObject jsonObject = new JSONObject();
                                    jsonObject.put("data", profitAmountChangePO);
                                    messageSender.send(RabbitMQConstant.RABBITMQ_AMOUNT_CHANGE_INFO_MANAGER_QUEUE, JSON.toJSONString(jsonObject),
                                            RabbitMQConstant.RABBITMQ_PAY_EXCHANGE,
                                            RabbitMQConstant.RABBITMQ_AMOUNT_CHANGE_INFO_ROUTING_KEY);
                                }
                            }
                        } else if ("5".equals(orderPO.getFeeType())) {
                            //根据项目编号查询物业增值信息
                            BigDecimal realTotalValue = new BigDecimal(realTotal);
                            PropertyValuePO propertyValuePO = iWechatPayDao.getPropertyValueInfo(projectId);
                            BigDecimal handlingFee = new BigDecimal(realTotalValue.multiply(new BigDecimal(propertyValuePO.getOpenTempPassPercent().toString())).multiply(new BigDecimal("0.01")).toString());
                            shareProfitBalance = new BigDecimal(decimalFormat.format(handlingFee));//四舍五入手续费
                        }
                        if ((shareProfitRuleInfoPO != null && (shareProfitRuleInfoPO.getType() == 1 || StringUtils.isNotBlank(iWechatPayDao.getRoomManage(orderPO.getFeeId())))) || "5".equals(orderPO.getFeeType())) {
                            Map<String, Object> balanceMap = new HashMap<>();
                            balanceMap.put("arithmeticFlag", "1");//运算: 0加,1减
                            balanceMap.put("amount", shareProfitBalance.toString());//金额
                            balanceMap.put("projectId", projectId);//项目编号
                            balanceMap.put("updateNameFlag", 1);//0可提现余额,1实时余额   为空都更新
                            messageSender.send(RabbitMQConstant.RABBITMQ_PROJECT_AMOUNT_MANAGER_QUEUE, JSON.toJSONString(balanceMap),
                                    RabbitMQConstant.RABBITMQ_PAY_EXCHANGE,
                                    RabbitMQConstant.RABBITMQ_PROJECT_AMOUNT_ROUTING_KEY);

                            //保存收取物业增值费用后资金变动明细 发送消息队列
                            AmountChangeInfoPO profitAmountChangePO = new AmountChangeInfoPO(LogicIdUtil.bussinessId(),
                                    shareProfitBalance, paramMap.get("transaction_id").toString(), "", "");
                            profitAmountChangePO.setStatus(DataStatusEnum.NORMAL.getType());
                            profitAmountChangePO.setProjectId(projectId);
                            profitAmountChangePO.setCreateTime(new Date());
                            profitAmountChangePO.setThirdPartyPayment(1);
                            profitAmountChangePO.setHandlingFee(new BigDecimal("0"));
                            String address = iWechatPayDao.getBillAddress(orderPO.getFeeId());
                            profitAmountChangePO.setRemark(StringUtils.isBlank(address) ? "临时通行物业增值分润扣除" : address + "物业增值分润扣除");
                            profitAmountChangePO.setTradeType(TradeTypeEnum.PROPERTY_ADD_VALUE.getType());
                            JSONObject jsonObject = new JSONObject();
                            jsonObject.put("data", profitAmountChangePO);
                            messageSender.send(RabbitMQConstant.RABBITMQ_AMOUNT_CHANGE_INFO_MANAGER_QUEUE, JSON.toJSONString(jsonObject),
                                    RabbitMQConstant.RABBITMQ_PAY_EXCHANGE,
                                    RabbitMQConstant.RABBITMQ_AMOUNT_CHANGE_INFO_ROUTING_KEY);
                        }
                    }
                }

                //如果账单类型为维修，将账单号发送消息队列
                if (StringUtils.isNotEmpty(orderPO.getFeeType())) {
                    if (("2").equals(orderPO.getFeeType())) {
                        JSONObject dataJs = new JSONObject();
                        dataJs.put("data", orderPO.getFeeId());
                        messageSender.send(RabbitMQConstant.RABBITMQ_REPAIR_MANAGER_COMPLETE_PAY_QUEUE,
                                JSON.toJSONString(dataJs), RabbitMQConstant.RABBITMQ_NON_CORE_EXCHANGE,
                                RabbitMQConstant.RABBITMQ_REPAIR_MANAGER_COMPLETE_PAY_ROUTING_KEY);
                    }
                }

                for (String feeId : feeIds) {
                    //如所交费用为1物业费时，将发送消息队列 修改app_user_project和room_info表中用户的欠费字段和推送云对讲房间和用户的指令 由于支付OK后要极光推送故，暂不使用异步
                    if (orderPO.getFeeType().equals("1")) {
                        payParkFeeNoticeVO.setFeeType("1");
//                    Map<String,Object> params=new HashMap<>();
//                    params.put("feeId", orderPO.getFeeId());
//
//                    messageSender.send(RabbitMQConstant.RABBITMQ_USER_ROOM_FORBIDDEN_QUEUE,JSON.toJSONString(params),
//                            RabbitMQConstant.RABBITMQ_PAY_EXCHANGE,
//                            RabbitMQConstant.RABBITMQ_USER_ROOM_FORBIDDEN_ROUTING_KEY);
                        List<AppUserAndRoomInfoVO> list = iUpdateUserAndRoomForbiddenStatusDao.getForbiddenInfo(feeId);
                        if (null != list && !list.isEmpty()) {
                            payParkFeeNoticeVO.setList(list);
                            List<String> userIdList = new ArrayList<>();
                            JSONArray pushRoom = new JSONArray();
                            JSONObject dataJs = new JSONObject();
                            for (AppUserAndRoomInfoVO roomInfoVO : list) {
                                List<String> roomIdList = new ArrayList<>();
                                //查询指定房间下是否还有未缴费的账单，如没有则添加至集合当中
                                if(iUpdateUserAndRoomForbiddenStatusDao.isArrearageByRoomInfo(roomInfoVO.getRoomId(),projectId) == 0){
                                    roomIdList.add(roomInfoVO.getRoomId());
                                    //修改room_info欠费状态
                                    if(roomIdList != null && !roomIdList.isEmpty()){
                                        iUpdateUserAndRoomForbiddenStatusDao.updateRoomStatus(roomIdList);
                                    }
                                }
                                Thread.sleep(200);
                                //查询用户在该项目下还有欠费的房间，若有则不添加至集合当中
                                if (iUpdateUserAndRoomForbiddenStatusDao.isUserArrearageProject(roomInfoVO.getUserId(), roomInfoVO.getProjectId()) == 0) {
                                    userIdList.add(roomInfoVO.getUserId());
                                }
                                JSONObject json = new JSONObject();
                                json.put("unitId", roomInfoVO.getUnitId());
                                json.put("buildId", roomInfoVO.getBuildId());
                                json.put("roomId", roomInfoVO.getRoomId());
                                pushRoom.add(json);
                            }

                            //修改app_user_project欠费状态
                            if(userIdList != null && !userIdList.isEmpty()){
                                iUpdateUserAndRoomForbiddenStatusDao.updateUserStatus(userIdList, list.get(0).getProjectId());
                            }

                            //向云对讲推送房间信息变更指令
                            List<DeviceBusinessChangeLogPO> changeLogPOS = new ArrayList<>();
                            DeviceBusinessChangeLogPO deviceBusinessChangeLogPO =
                                    new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_ROOM, pushRoom.toJSONString(), list.get(0).getProjectId());
                            changeLogPOS.add(deviceBusinessChangeLogPO);
                            if (!changeLogPOS.isEmpty()) {
                                dataJs = new JSONObject();
                                dataJs.put("data", changeLogPOS);

                                messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE,
                                        JsonUtil.toJSON(dataJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE,
                                        RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
                            }
                        }
                    }
                }
                if (orderPO.getFeeType().equals("1")) {
                    //账单为物业抄表费 查询账单下所有的房间
                    List<String> roomIds = iWechatPayDao.getAllRoomByBill(orderPO.getFeeId().split(","));
                    if (roomIds.size() > 0) {
                        List<DeviceBusinessChangeLogPO> changes = new ArrayList<>();
                        List<DeviceBusinessElevatorChangeLogPO> elevatorChanges = new ArrayList<>();
                        List<DeviceBusinessEntranceChangeLogPO> entranceChanges = new ArrayList<>();
                        List<Map<String, Object>> roomList = new ArrayList<>();
                        for (String roomId : roomIds) {
                            Map<String, Object> roomMap = new HashMap<>();
                            roomMap.put("roomId", roomId);
                            roomList.add(roomMap);
                        }
                        //推送房间更新消息
                        DeviceBusinessChangeLogPO po = new DeviceBusinessChangeLogPO(SmartCommunityEnum.PUSH_ROOM, JsonUtil.toJSON(roomList), projectId);
                        changes.add(po);
                        DeviceBusinessElevatorChangeLogPO elevatorPo = new DeviceBusinessElevatorChangeLogPO(projectId, CloudElevatorChangeBusinessEnum.PUSH_ROOM_PWD, JsonUtil.toJSON(roomList));
                        elevatorChanges.add(elevatorPo);
                        DeviceBusinessEntranceChangeLogPO entrancePO = new DeviceBusinessEntranceChangeLogPO(projectId, CloudEntranceChangeBusinessEnum.PUSH_ROOM_PWD, JsonUtil.toJSON(roomList));
                        entranceChanges.add(entrancePO);
                        JSONObject dataJs = new JSONObject();
                        dataJs.put("data", changes);
                        //发送云对讲业务指令
                        messageSender.send(RabbitMQConstant.RABBITMQ_HANDLE_SMART_COMMUNITY_ORDERS_QUEUE, JsonUtil.toJSON(dataJs), RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_EXCHANGE, RabbitMQConstant.RABBITMQ_SMART_COMMUNITY_ORDERS_ROUTING_KEY);
                        dataJs.put("data", elevatorChanges);
                        //推送云电梯房间信息
                        messageSender.send(
                                RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                                JsonUtil.toJSON(dataJs),
                                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
                        //发送云门禁指令
                        dataJs.put("data", entranceChanges);
                        messageSender.send(
                                RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ENTRANCE_CHANGE_BUSINESS_QUEUE,
                                JSON.toJSONString(dataJs),
                                RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_EXCHANGE,
                                RabbitMQConstant.RABBITMQ_CLOUD_ENTRANCE_CHANGE_BUSINESS_ROUTING_KEY
                        );
                    }
                }
                    payParkFeeNoticeVO.setCarIssueDTO(carIssueDTO);
                    payParkFeeNoticeVO.setParkingCostsDTO(costsDTO);
                    payParkFeeNoticeVO.setFeeType(orderPO.getFeeType());
                    payParkFeeNoticeVO.setWechatReturnNotice(wechatReturnNotice);
                    payParkFeeNoticeVO.setProjectId(projectId);
                    return payParkFeeNoticeVO;
            }
        } catch (Exception e) {
            throw new DataAccessException("【App_微信支付结果回调失败】", e);
        }
        return null;
    }

    /**
     * <desc>
     * 演示版微信支付结果回调通知
     * <desc/>
     *
     * @param
     * @return
     * @author Juguang.S
     * @createDate 2018/4/25
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public String showPayResultNotice(String rturnInfo) {

        try {
            //对微信后台请求传参进行转换格式及校验sign是否合法
//            Map<Object, Object> paramMap = XMLParser.getMapFromXML(rturnInfo, "XML");
            Map<Object, Object> paramMap = XMLParser.xmlString2Map(rturnInfo);
            if (StringUtils.isNotEmpty(paramMap.get("return_code").toString()) && paramMap.get("return_code").toString().equals("SUCCESS")) {
                Boolean bo = Md5EncryptUtil.checkWechatResponseSign(rturnInfo, KEY_APPSECRET);

                //校验支付通知返回的金额和下订单时数据库保存的金额的一致性及sign的合法性
                if (!bo) {
                    return null;
                }
                PaymentTradePO orderPO = iWechatPayDao.getOrderByTradeId(paramMap.get("out_trade_no").toString());

                //商户系统对处理重复的通知的校验  根据商户订单号从数据库中查出该订单的是否收到支付后的回调

                if (orderPO.getSuccessReturn() == 1) {
                    return "<xml>\n" + "  <return_code><![CDATA[SUCCESS]]></return_code>\n" + "  <return_msg><![CDATA[OK]]></return_msg>\n" + "</xml>";
                }

                orderPO.setTransactionId(paramMap.get("transaction_id").toString());

                String reg = "(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})";
                String date = paramMap.get("time_end").toString().replaceAll(reg, "$1/$2/$3 $4:$5:$6");
                orderPO.setSuccessTime(new Date(date));
                orderPO.setUpdateTime(new Date());
                orderPO.setTradeStatus(PayStatusEnum.SUCCESS_PAY.getType());
                orderPO.setTransactionId(paramMap.get("transaction_id").toString());
                orderPO.setSuccessReturn(1);

                iWechatPayDao.update(SqlUtil.durableData(orderPO, PlatformConstants.TABLE_UPDATE));

                //保存余额变动流水表中的数据
                AppUserBalanceChangeRecordPO recordPO = new AppUserBalanceChangeRecordPO();
                recordPO.setMoney(orderPO.getPrice());
                recordPO.setRecordId(RandomUtil.getRandomStringByLength(32));
                recordPO.setRecordType(1);
                recordPO.setRecordSource(1);
                recordPO.setSourceId(paramMap.get("transaction_id").toString());
                recordPO.setUserId(orderPO.getUserId());
                recordPO.setStatus(DataStatusEnum.NORMAL.getType());
                recordPO.setCreateTime(new Date());
                iWechatPayDao.save(SqlUtil.durableData(recordPO, PlatformConstants.TABLE_SAVE));

                //更新用户账号余额 首先根据userId查出是否有该用户的余额信息，如没有则插入数据，如有则更新

                Map<String, Object> params = new HashMap<>();
                params.put("userId", orderPO.getUserId());
                AppUserAccountBalancePO balancePO = iAccountBalanceDao.getBalanceByParams(params);
                if (balancePO == null) {
                    AppUserAccountBalancePO userPO = new AppUserAccountBalancePO(orderPO.getUserId(), orderPO.getPrice());
                    userPO.setCreateTime(new Date());
                    userPO.setStatus(DataStatusEnum.NORMAL.getType());
                    iAccountBalanceDao.save(SqlUtil.durableData(userPO, PlatformConstants.TABLE_SAVE));
                    return "<xml>\n" + "  <return_code><![CDATA[SUCCESS]]></return_code>\n" + "  <return_msg><![CDATA[OK]]></return_msg>\n" + "</xml>";
                }
                BigDecimal p = orderPO.getPrice();
                iAccountBalanceDao.updateAccountBalance(orderPO.getPrice(), orderPO.getUserId(), new Date());

                return "<xml>\n" + "  <return_code><![CDATA[SUCCESS]]></return_code>\n" + "  <return_msg><![CDATA[OK]]></return_msg>\n" + "</xml>";

            }
        } catch (Exception e) {
            throw new DataAccessException("【演示版App_微信支付结果回调失败】", e);
        }
        return null;
    }

    /**
     * <desc>
     * 根据商户订单号查询订单
     * <desc/>
     *
     * @param tradeId 商户订单号
     * @return
     * @author Juguang.S
     * @createDate 2018/4/25
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Map<String, Object> getOrderBytradeId(String tradeId) {

        try {
            Map<Object, Object> map = new HashMap<>();
            map.put("appid", APPID);
            map.put("mch_id", MCHID);
            map.put("out_trade_no", tradeId);
            map.put("nonce_str", RandomUtil.getRandomStringByLength(32));

            //根据算法生成签名
            String sign = Md5EncryptUtil.getWechatSign(map, KEY_APPSECRET);
            map.put("sign", sign);

            //将参数转换成xml
            String paramXML = XMLParser.converterPayPalm(map);

            //通过HTTPS请求调用微信的统一下单请求
            String responseXML = HttpProtocolUtil.httpPost(ORDERURL, paramXML);
            Map<String, Object> returnData = new HashMap<>();

            //检验API返回的数据里面的签名是否合法，避免数据在传输的过程中被第三方篡改.

            /*Boolean bo = Md5EncryptUtil.checkWechatResponseSign(responseXML,KEY_APPSECRET);
            if (!bo) {
                returnData.put("status",1);
                return returnData;
            }*/

            //将返回数据XML转为Map格式
            Map<Object, Object> responseMap = XMLParser.xmlString2Map(responseXML);

            Map<String, Object> data = new HashMap<>();
            if (responseMap.get("return_code").toString().contains("SUCCESS") && responseMap.get("result_code").toString().contains("SUCCESS")) {
                data.put("appid", responseMap.get("appid").toString());
                data.put("mchId", responseMap.get("mch_id").toString());
                data.put("tradeState", responseMap.get("trade_state").toString());
                if (responseMap.get("trade_state_desc").toString().equals("支付成功")) {
                    data.put("totalFee", (Double.parseDouble(responseMap.get("total_fee").toString())) / 100);
                }
                data.put("transactionId", responseMap.get("transaction_id"));
                data.put("outTradeNo", responseMap.get("out_trade_no").toString());
                if (responseMap.get("trade_state_desc").toString().equals("支付成功")) {
                    data.put("timeEnd", responseMap.get("time_end").toString());
                }
                data.put("tradeStateDesc", responseMap.get("trade_state_desc").toString());
            }
            return data;
        } catch (Exception e) {
            throw new DataAccessException("【演示版App_微信支付】根据商户订单号或微信订单号查询订单", e);
        }
    }

    /**
     * <desc>
     * 定时任务获取前一天的微信对账单 由于对账业务比较繁琐，防止超时故另开启一个线程异步运行
     * <desc/>
     *
     * @param
     * @return
     * @author Juguang.S
     * @createDate 2018/8/28
     */
    @Override
    public void downloadWechatBill() throws Exception {

        cachedThreadPool.execute(() -> {
            try {
                Calendar ca = Calendar.getInstance();
                ca.setTime(new Date());
                ca.add(Calendar.DATE, -1);
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
                SimpleDateFormat dateFormatStr = new SimpleDateFormat("yyyy-MM-dd");
                SimpleDateFormat dateFormatTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

                Map<Object, Object> map = new HashMap<>();
                map.put("appid", APPID);
                map.put("mch_id", MCHID);
                map.put("nonce_str", RandomUtil.getRandomStringByLength(32));
                map.put("bill_date", dateFormat.format(ca.getTime()));
                map.put("bill_type", "ALL");
                map.put("tar_type", "GZIP");

                //根据算法生成签名
                String sign = Md5EncryptUtil.getWechatSign(map, KEY_APPSECRET);
                map.put("sign", sign);

                //将参数转换成xml
                String paramXML = XMLParser.converterPayPalm(map);

                // 下载文件
                LOG.info("【微信对账业务】-开始下载账单");
                Boolean downloadSuccess = downloadFile(DOWNLOADB_BILL_URL, FileCatalogEnum.WECHAT_DOWNLOAD_BILL_FILE.getType() + dateFormat.format(ca.getTime()) + ".gzip", paramXML);
                if (downloadSuccess) {
                    LOG.info("【微信对账业务】-下载账单成功");
                    //如所传日期有账单并下载成功，刚将其上传至ftp服务器做备份
                    //FileInputStream in=new FileInputStream(new File("d:\\billDownload\\"+dateFormat.format(ca.getTime())+".gzip"));
                    FileInputStream in = new FileInputStream(new File(FileCatalogEnum.WECHAT_DOWNLOAD_BILL_FILE.getType() + dateFormat.format(ca.getTime()) + ".gzip"));
                    uploadFile(FILE_FTP_HOST, Integer.valueOf(FILE_FTP_PORT), FILE_FTP_USERNAME, FILE_FTP_PASSWORD, FileCatalogEnum.WECHAT_DOWNLOAD_BILL_FILE.getType(), dateFormat.format(ca.getTime()) + ".gzip", in);
                    //从服务器所存储账单的路径下读取账单信息并开始对账服务
                    List<String[]> billInfoArr = this.readGzipBillInfo(FileCatalogEnum.WECHAT_DOWNLOAD_BILL_FILE.getType() + dateFormat.format(ca.getTime()) + ".gzip");
                    List<Map<String, Object>> saveDiffShortList = new ArrayList<>();
                    List<Map<String, Object>> saveDiffLongList = new ArrayList<>();

                    if (billInfoArr == null) {
                        LOG.info("【微信对账业务】-总金额相等无须逐一对账");
                        //无须对账将服务器中的文件删除
                        this.deleteServerFile(FileCatalogEnum.WECHAT_DOWNLOAD_BILL_FILE.getType() + dateFormat.format(ca.getTime()) + ".gzip");
                        return;
                    }

                    if (billInfoArr.size() > 0) {
                        //此处为对账业务逻辑处理
                        //获取下载账单日期的商户后台的当日订单
                        List<PaymentTradePO> paymentTradePOList = iWechatPayDao.getOrderByBillDate(dateFormatStr.format(ca.getTime()));
                        LOG.info("【微信对账业务】-开始对账");
                        //首先以商户后台的订单为主去比对微信的订单，如商户有订单而微信没有则标记为短款，如两者都有但金额不一致则标记为金额不一致
                        for (PaymentTradePO tradePO : paymentTradePOList) {
                            int count = 1;
                            String tradeId = tradePO.getTradeId();
                            String account = tradePO.getPrice().setScale(2, BigDecimal.ROUND_HALF_UP).toString();
                            for (String[] strArr : billInfoArr) {
                                Date tradeTime = dateFormatTime.parse(strArr[0]);
                                String appid = strArr[1];
                                String mchid = strArr[2];
                                String wechatOrderId = strArr[5];
                                String wechatTradeId = strArr[6];
                                String wechatAccount = strArr[12];
                                if (tradeId.equals(wechatTradeId) && account.equals(wechatAccount)) {
                                    billInfoArr.remove(count - 1);
                                    break;
                                }
                                //出现金额不一致的情况
                                else if (tradeId.equals(wechatTradeId) && !account.equals(wechatAccount)) {
                                    WechatCheckAccountOrderDiffPO diffPO = new WechatCheckAccountOrderDiffPO(appid, mchid);
                                    diffPO.setOrderDiffId(LogicIdUtil.bussinessId());
                                    diffPO.setBussinessOrderNum(wechatTradeId);
                                    diffPO.setWechatOrderNum(wechatOrderId);
                                    diffPO.setOrderTime(tradePO.getCreateTime());
                                    diffPO.setTradeSuccessTime(tradeTime);
                                    diffPO.setWechatTradeAmount(new BigDecimal(wechatAccount));
                                    diffPO.setBussinessTradeAmount(tradePO.getPrice());
                                    diffPO.setDiffType(WechatCheckBilDiffTypeEnum.INCONSISTENT_AMOUNT.getType());
                                    diffPO.setDiffOrderStatus(WechatCheckBilDiffStatusEnum.NOT_FLAT_ACCOUNT.getType());
                                    diffPO.setStatus(DataStatusEnum.NORMAL.getType());
                                    diffPO.setCreateTime(new Date());
                                    saveDiffShortList.add(SqlUtil.durableData(diffPO, PlatformConstants.TABLE_SAVE));
                                    break;
                                }
                                if (count == billInfoArr.size()) {
                                    //此时就出现短款
                                    if (!tradeId.equals(wechatTradeId)) {
                                        WechatCheckAccountOrderDiffPO diffPO = new WechatCheckAccountOrderDiffPO(appid, mchid);
                                        diffPO.setOrderDiffId(LogicIdUtil.bussinessId());
                                        diffPO.setBussinessOrderNum(tradeId);
                                        diffPO.setWechatOrderNum(tradePO.getTransactionId());
                                        diffPO.setOrderTime(tradePO.getCreateTime());
                                        diffPO.setTradeSuccessTime(tradePO.getUpdateTime());
                                        diffPO.setBussinessTradeAmount(tradePO.getPrice());
                                        diffPO.setDiffType(WechatCheckBilDiffTypeEnum.SHORT_PARAGRAPH.getType());
                                        diffPO.setDiffOrderStatus(WechatCheckBilDiffStatusEnum.NOT_FLAT_ACCOUNT.getType());
                                        diffPO.setStatus(DataStatusEnum.NORMAL.getType());
                                        diffPO.setCreateTime(new Date());
                                        saveDiffShortList.add(SqlUtil.durableData(diffPO, PlatformConstants.TABLE_SAVE));
                                    }
                                }
                                count++;
                            }
                        }
                        LOG.info("【微信对账业务】-短款对账完毕");
                        if (!saveDiffShortList.isEmpty()) {   //将对账有出入的数据批量保存
                            iWechatPayDao.batchSave(saveDiffShortList);
                        }
                        //再以微信订单为主比对商户后台订单，如微信订单有，商户后台没有则有可能是因为银行日切日早于商户的所以造成的数据出入，故先在日期中的短款数据中匹配，如有则平账，否则保存为长款
                        //从服务器所存储账单的路径下读取账单信息并开始对账服务
                        billInfoArr = this.readGzipBillInfo(FileCatalogEnum.WECHAT_DOWNLOAD_BILL_FILE.getType() + dateFormat.format(ca.getTime()) + ".gzip");
                        for (String[] strArr : billInfoArr) {
                            int count = 1;
                            Date tradeTime = dateFormatTime.parse(strArr[0]);
                            String appid = strArr[1];
                            String mchid = strArr[2];
                            String wechatOrderId = strArr[5];
                            String wechatTradeId = strArr[6];
                            String wechatAccount = strArr[12];
                            for (PaymentTradePO tradePO : paymentTradePOList) {
                                String tradeId = tradePO.getTradeId();
                                String account = tradePO.getPrice().setScale(2, BigDecimal.ROUND_HALF_UP).toString();
                                if (wechatTradeId.equals(tradeId) && wechatAccount.equals(account)) {
                                    paymentTradePOList.remove(count - 1);
                                    break;
                                }
                                //出现金额不一致的情况
                                else if (tradeId.equals(wechatTradeId) && !account.equals(wechatAccount)) {
                                    WechatCheckAccountOrderDiffPO diffPO = new WechatCheckAccountOrderDiffPO(appid, mchid);
                                    diffPO.setOrderDiffId(LogicIdUtil.bussinessId());
                                    diffPO.setBussinessOrderNum(wechatTradeId);
                                    diffPO.setWechatOrderNum(wechatOrderId);
                                    diffPO.setOrderTime(tradePO.getCreateTime());
                                    diffPO.setTradeSuccessTime(tradeTime);
                                    diffPO.setWechatTradeAmount(new BigDecimal(wechatAccount));
                                    diffPO.setBussinessTradeAmount(tradePO.getPrice());
                                    diffPO.setDiffType(WechatCheckBilDiffTypeEnum.INCONSISTENT_AMOUNT.getType());
                                    diffPO.setDiffOrderStatus(WechatCheckBilDiffStatusEnum.NOT_FLAT_ACCOUNT.getType());
                                    diffPO.setStatus(DataStatusEnum.NORMAL.getType());
                                    diffPO.setCreateTime(new Date());
                                    if (iWechatPayDao.getInconsistentAmountByTradeId(wechatTradeId) == 0) {
                                        saveDiffLongList.add(SqlUtil.durableData(diffPO, PlatformConstants.TABLE_SAVE));
                                    }
                                    break;
                                }
                                if (count == paymentTradePOList.size()) {
                                    //此时就出现长款
                                    if (!wechatTradeId.equals(tradeId)) {
                                        //先排除因微信日切日早于商户平台的，故先在日期中的短款数据中匹配，如有则平账，否则保存为长款
                                        Integer infoCount = iWechatPayDao.getIsCheckDiffBillByTradeId(wechatTradeId, wechatAccount);
                                        if (infoCount > 0) {
                                            iWechatPayDao.updateDiffOrderStatus(wechatTradeId);
                                        } else {
                                            WechatCheckAccountOrderDiffPO diffPO = new WechatCheckAccountOrderDiffPO(appid, mchid);
                                            diffPO.setOrderDiffId(LogicIdUtil.bussinessId());
                                            diffPO.setBussinessOrderNum(wechatTradeId);
                                            diffPO.setWechatOrderNum(wechatOrderId);
                                            diffPO.setTradeSuccessTime(tradeTime);
                                            diffPO.setWechatTradeAmount(new BigDecimal(wechatAccount));
                                            diffPO.setDiffType(WechatCheckBilDiffTypeEnum.LONG_SECTION.getType());
                                            diffPO.setDiffOrderStatus(WechatCheckBilDiffStatusEnum.NOT_FLAT_ACCOUNT.getType());
                                            diffPO.setStatus(DataStatusEnum.NORMAL.getType());
                                            diffPO.setCreateTime(new Date());
                                            saveDiffLongList.add(SqlUtil.durableData(diffPO, PlatformConstants.TABLE_SAVE));
                                        }
                                    }
                                }
                                count++;
                            }
                        }
                        LOG.info("【微信对账业务】-长款对账完毕");
                        if (!saveDiffLongList.isEmpty()) {   //将对账有出入的数据批量保存
                            iWechatPayDao.batchSave(saveDiffLongList);
                        }
                    }
                    //对账逻辑处理完毕，将服务器中的文件删除
                    this.deleteServerFile(FileCatalogEnum.WECHAT_DOWNLOAD_BILL_FILE.getType() + dateFormat.format(ca.getTime()) + ".gzip");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

    }

    /**
     * <desc>
     * 查询第三方支付管理微信支付是否被禁用
     * <desc/>
     *
     * @param thirdPayType 1微信支付 2银联转账
     * @return
     * @author Juguang.S
     * @createDate 2018/9/26
     */
    @Override
    public Integer getThirdPayStatus(Integer thirdPayType) {
        return iWechatPayDao.getThirdPayStatus(thirdPayType);
    }

    /**
     * <desc>
     * 查询该账单是否已被支付
     * <desc/>
     *
     * @param billsId 账单编号
     * @return
     * @author Juguang.S
     * @createDate 2018/10/09
     */
    @Override
    public Integer getBillStatus(String billsId) {
        String[] feeIds = billsId.split(",");
        return iWechatPayDao.getBillStatus(feeIds);
    }

    /**
     * <desc>
     * 保存停车场错误指令
     * <desc/>
     *
     * @param projectId      项目编号
     * @param requestContent 请求内容
     * @return
     * @author Juguang.S
     * @createDate 2018/11/15
     */
    @Override
    public void sendMessager(String projectId, String requestContent, Integer payType) throws Exception {

        TimeTaskParkingErrorOrderPO po = new TimeTaskParkingErrorOrderPO(projectId, requestContent, payType, ParkingOrderTypeEnum.CAR_ISSUE.getDescription());
        Map<String, Object> map = new HashMap<>();
        map.put("message", po);
        messageSender.send(RabbitMQConstant.RABBITMQ_PARKING_ERROR_ORDER_QUEUE, JsonUtil.toJSON(map),
                RabbitMQConstant.RABBITMQ_PARKING_ORDER_EXCHANGE, RabbitMQConstant.RABBITMQ_PARKING_ERROR_ORDER_QUEUE_KEY);
    }

    /**
     * <desc>
     * 处理零元支付情况通知富士
     * </desc>
     *
     * @param billsId 账单ID
     * @return 缴费记录
     * @author Juguang.S
     * @createDate 2018/12/13
     */
    @Override
    public AppPayParkFeeNoticeVO getZeroPaymentNotice(String billsId) throws Exception {
        AppPayParkFeeNoticeVO payParkFeeNoticeVO = new AppPayParkFeeNoticeVO();
        PaymentParkingCostsDTO costsDTO = null;
        costsDTO = iWechatPayDao.getTemCarInfoByBillId(billsId);
        if(costsDTO==null){
            new PaymentParkingCostsDTO();
        }
        costsDTO.setPayMoney(new BigDecimal("0"));
        costsDTO.setCarType("2C");
        costsDTO.setFreeMoney(new BigDecimal("0"));
        costsDTO.setPayType("2");
        costsDTO.setReDate(sdf2.format(new Date()));
        payParkFeeNoticeVO.setParkingCostsDTO(costsDTO);
        return payParkFeeNoticeVO;
    }

    /**
     * <desc>
     * 获取前一天的微信对账单的方法
     * <desc/>
     *
     * @param
     * @return
     * @author Juguang.S
     * @createDate 2018/8/28
     */
    public static Boolean downloadFile(String urlPath, String saveDir, String content) throws Exception {
        URL url = new URL(urlPath);
        // 连接类的父类，抽象类
        URLConnection urlConnection = url.openConnection();
        // http的连接类
        HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
        // 设定请求的方法，默认是GET（对于知识库的附件服务器必须是GET，如果是POST会返回405。流程附件迁移功能里面必须是POST，有所区分。）
        httpURLConnection.setRequestMethod("POST");
        httpURLConnection.setDoOutput(true);
        httpURLConnection.setRequestProperty("Accept", "application/json;");
        httpURLConnection.setRequestProperty("Content-Type", "application/json;charset=utf-8");

        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(httpURLConnection.getOutputStream(),
                PlatformConstants.DEFAULT_CHARSET));

        writer.write(content.toString());
        writer.flush();
        writer.close();
        // 设置字符编码
        // 打开到此 URL 引用的资源的通信链接（如果尚未建立这样的连接）。
        int code = httpURLConnection.getResponseCode();

        InputStream inputStream = httpURLConnection.getInputStream();
        if (inputStream.available() != 149) {
            System.out.println("结果：" + inputStream.available());
            File file = new File(saveDir);
            if (!file.getParentFile().exists()) {
                boolean result = file.getParentFile().mkdirs();
                if (!result) {
                    System.out.println("创建失败");
                }
            }
            OutputStream out = new FileOutputStream(file);
            int size = 0;
            int lent = 0;
            byte[] buf = new byte[1024];
            while ((size = inputStream.read(buf)) != -1) {
                lent += size;
                out.write(buf, 0, size);
            }
            inputStream.close();
            out.close();
            return true;
        }
        LOG.info("【微信对账业务】-T日无账单");
        return false;
    }

    /**
     * <desc>
     * 读取压缩文件中的账单信息的方法
     * <desc/>
     *
     * @param
     * @return
     * @author Juguang.S
     * @createDate 2018/8/28
     */
    public List<String[]> readGzipBillInfo(String path) {

        Calendar ca = Calendar.getInstance();
        ca.setTime(new Date());
        ca.add(Calendar.DATE, -1);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat dateFormatStr = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat dateFormatTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            File file = new File(path);
            if (!file.exists()) {
                return null;
            }
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(
                            new GZIPInputStream(
                                    new FileInputStream(path)), "utf-8"));

            String line = null;
            StringBuilder result = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                result.append(line);

            }

            String tradeMsg = result.substring(result.indexOf("`"));
            //首先比较微信对账中的总金额和商户后台订单总金额是否相等，如相等则不进行逐一比对
            String totalAmount = iWechatPayDao.getTradeTotal(dateFormatStr.format(ca.getTime()));
            String listStr = "";
            String objStr = "";
            if (tradeMsg.indexOf("总交易单数") >= 0) {
                listStr = tradeMsg.substring(0, tradeMsg.indexOf("总交易单数"));
                objStr = tradeMsg.substring(tradeMsg.indexOf("总交易单数"));
                String[] i = objStr.replaceAll("`", "").split("手续费总金额");
                String[] acount = i[1].split(",");
                if (acount[1].equals(totalAmount)) {
                    return null;
                }
            }
            String tradeInfo = tradeMsg.substring(0, tradeMsg.indexOf("总")).replace("`", "");// 去掉汇总数据，并且去掉'`'
            //用spilt方法拿出每一天数据放进数组里。之后再用spilt方法把数据放进二维数组里。
            String[] tradeArray = tradeInfo.split("%");  // 根据%来区分
            List<String[]> tradeList = new ArrayList<>();
            String[] tradeDetailArray = null;
            for (String tradeDetailInfo : tradeArray) {
                tradeDetailArray = tradeDetailInfo.split(",");
                tradeList.add(tradeDetailArray);
            }

            String tradeTotalMsg = tradeMsg.substring(tradeMsg.indexOf("总"));

            String tradeTotalInfo = tradeTotalMsg.substring(tradeTotalMsg.indexOf("`"));

            System.out.println("result:" + result);
            System.out.println("tradeMsg:" + tradeMsg);
            System.out.println("tradeInfo:" + tradeInfo);
            System.out.println("tradeTotalMsg:" + tradeTotalMsg);
            System.out.println("tradeTotalInfo:" + tradeTotalInfo);
            return tradeList;

        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Description: 向FTP服务器上传文件
     *
     * @param url      FTP服务器hostname
     * @param port     FTP服务器端口
     * @param username FTP登录账号
     * @param password FTP登录密码
     * @param path     FTP服务器保存目录
     * @param filename 上传到FTP服务器上的文件名
     * @param input    输入流
     * @return 成功返回true，否则返回false
     */
    public static void uploadFile(String url, int port, String username, String password, String path, String filename, InputStream input) {
        boolean success = false;
        Map<String, Object> map = new HashMap<String, Object>();
        String filepath = "";
        FTPClient ftp = new FTPClient();
        try {
            int reply;
            ftp.connect(url, port);//连接FTP服务器
            //如果采用默认端口，可以使用ftp.connect(url)的方式直接连接FTP服务器
            ftp.login(username, password);//登录
            reply = ftp.getReplyCode();

            //判断reply的code是否正常，一般正常为2开头的code
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                map.put("status", success);
                map.put("filepath", filepath);
            }

            boolean a = ftp.changeWorkingDirectory("/");
            System.out.println("转换目录结果1:" + a);

            if (StringUtils.isBlank(path) || path.equals("/")) {//如果输入的路径为空或者为根路径，则不转换操作目录

            } else {//否则创建想要上传文件的目录，并且将操作目录转为新创建的目录
                ftp.makeDirectory(path);
                boolean b = ftp.changeWorkingDirectory(path);
                System.out.println("转换目录结果2:" + b);
            }

            //ftp上传文件是以文本形式传输的，所以多媒体文件会失真，需要转为二进制形式传输
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            //转码后可以文件名可以为中文
            ftp.storeFile(new String(filename.getBytes("GBK"), "iso-8859-1"), input);

            input.close();
            ftp.logout();
            LOG.info("【微信对账业务】-账单成功上传至FTP服务器");
/*            success = true;
            filepath = "ftp://"+url+":"+port+"/"+path+"/"+filename;
            map.put("status", success);
            map.put("filepath", filepath);*/
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (Exception ioe) {

                }
            }
        }
    }

    /**
     * 删除服务上的文件
     *
     * @param filePath 路径
     * @return
     * @author Juguang.S
     * @date 2018/08/29
     */
    public static boolean deleteServerFile(String filePath) {
        boolean delete_flag = false;
        File file = new File(filePath);
        if (file.exists() && file.isFile() && file.delete())
            delete_flag = true;
        else
            delete_flag = false;
        return delete_flag;
    }

    /**
     * <desc>
     * 保存月卡缴费记录
     * </desc>
     *
     * @param recordPO 保存数据
     * @return
     * @author Juguang.S
     * @createDate 2018/11/08
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public PropertyCardPaymentRecordPO saveMonthCardFeeRecord(PropertyCardPaymentRecordPO recordPO) throws Exception {

        Calendar rightNow = Calendar.getInstance();
        recordPO.setStatus(DataStatusEnum.NORMAL.getType());
        recordPO.setCreateTime(new Date());
        //获取此时月卡有效期的截止日期并计算出续费后的截止日期
        String endTime = iWechatPayDao.getMonthCarEndTime(recordPO.getCarId());
        //如果截止时间为空则开始时间从当日算起
        if (StringUtils.isEmpty(endTime)) {
            recordPO.setStartTime(new Date());
            rightNow.setTime(new Date());
        } else {
            recordPO.setStartTime(sdf.parse(getSpecifiedDayAfter(endTime)));
            rightNow.setTime(sdf.parse(endTime));
        }
        rightNow.add(Calendar.MONTH, recordPO.getMonth());
        Date dt1 = rightNow.getTime();
        String reStr = sdf.format(dt1);
        String str = String.format("%s%s", reStr, " 23:59:59");
        recordPO.setEndTime(sdf2.parse(str));
        iWechatPayDao.save(SqlUtil.durableData(recordPO, PlatformConstants.TABLE_SAVE));
        return recordPO;
    }

    //指定时间的后一天
    public String getSpecifiedDayAfter(String specifiedDay) {
        Calendar c = Calendar.getInstance();
        Date date = null;
        try {
            date = new SimpleDateFormat("yy-MM-dd").parse(specifiedDay);
        } catch (Exception e) {
            e.printStackTrace();
        }
        c.setTime(date);
        int day = c.get(Calendar.DATE);
        c.set(Calendar.DATE, day + 1);

        String dayAfter = new SimpleDateFormat("yyyy-MM-dd").format(c.getTime());
        return dayAfter;
    }
    /**
     * <desc>
     *      查询账单的金额
     * <desc/>
     * @param billsId 账单编号
     * @param type 支付类型 1代表除云服务费外的缴费 2代表云服务费的缴费
     * @return
     * @author Juguang.S
     * @createDate 2019/09/17
     */
    public String getBillTotal(String billsId,Integer type){
        if(type==2){
            return iWechatPayDao.getTotalByCloudServiceCost(billsId);
        }else{
            String[] feeIds = billsId.split(",");
            return iWechatPayDao.getTotalByBillId(feeIds);
        }

    }
}